﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.Serialization;
//using QbservableCore.Serialization.SDK;
using QbservableCore.Serialization.Helpers;

namespace QbservableCore.Serialization
{
    /// <summary>
    /// Serializable class for all Method call expression
    /// </summary>
    /// <example>
    /// collection.Select(() => {});
    /// </example>
    [DataContract]
    public class MethodCallNode : ExpRepresentationBase
    {
        [DataMember]
        public ExpRepresentationBase Instance { get; set; }

        [DataMember]
        public ExpRepresentationBase[] Arguments { get; set; }

        [DataMember]
        public SerializableMethodBase MethodContextToken { get; set; }

        [DataMember]
        public string MethodName { get; set; }

        protected internal override Expression ToExpression(ExepressionBuilderCache exepressionBuilderCache)
        {
            Expression[] args = new Expression[Arguments.Length];
            for (int index = 0; index < args.Length; index++)
            {
                args[index] = Arguments[index].ToExpression(exepressionBuilderCache);
            }
            //var method = (MethodInfo)MethodContextToken.Deserialize();
            var method = (MethodInfo)MethodContextToken.Method;
            Expression instance = null;
            if (Instance != null)
            {
                instance = Instance.ToExpression(exepressionBuilderCache);
            }
            return Expression.Call(instance, method, args);
        }

        protected override void TraverseChildren(Func<ExpRepresentationBase, ExpRepresentationBase> action)
        {
            if (Instance != null)
            {
                Instance = Instance.Traverse(action);
            }
            TraverseNodes(Arguments, action);
        }

        public override string ToString()
        {
            string instance = Instance != null ? Instance.ToString() + "." : string.Empty;
            string args = string.Join(", ", Arguments.Cast<object>());
            return string.Format("{0}{1}({2})", instance, MethodName, args);
        }
    }
}